package com.feng.yupaoback.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.yupaoback.common.ErrorCode;
import com.feng.yupaoback.enums.TeamStatusEnum;
import com.feng.yupaoback.exception.BusinessException;
import com.feng.yupaoback.pojo.dto.TeamJoinRequest;
import com.feng.yupaoback.pojo.dto.TeamQueryRequest;
import com.feng.yupaoback.pojo.dto.TeamQuitRequest;
import com.feng.yupaoback.pojo.dto.TeamUpdateRequest;
import com.feng.yupaoback.pojo.entity.Team;
import com.feng.yupaoback.pojo.entity.User;
import com.feng.yupaoback.pojo.entity.UserTeam;
import com.feng.yupaoback.pojo.vo.TeamUserVO;
import com.feng.yupaoback.pojo.vo.UserVO;
import com.feng.yupaoback.service.TeamService;
import com.feng.yupaoback.mapper.TeamMapper;
import com.feng.yupaoback.service.UserService;
import com.feng.yupaoback.service.UserTeamService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
* @author 34689
* @description 针对表【yu_pao_team(队伍)】的数据库操作Service实现
* @createDate 2025-07-14 19:13:40
*/
@Service
@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Resource
    private UserTeamService userTeamService;

    @Resource
    private UserService userService;

    @Override
    public Page<Team> getTeamListPage(String text, long pageNum, int status) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if ("".equals(text) || text == null) {
            queryWrapper.like("name", text);
        }
        queryWrapper.eq("status", status);
        return this.page(new Page<>(pageNum, 2), queryWrapper);
    }

    /**
     * 添加队伍
     * @param team 队伍信息
     * @param loginUser 当前用户
     * @return 队伍id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public long addTeam(Team team, User loginUser) {
        // 1. 请求参数是否为空？
        if (team == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请求参数为空！");
        }

        // 2. 是否登录，未登录不允许创建
        if (loginUser == null){
            throw new BusinessException(ErrorCode.NOT_LOGIN, "未登录！");
        }

        final int id = loginUser.getId();

        // 3. 校验信息
        //   1. 队伍人数 > 1 且 <= 20
        int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);
        if (maxNum < 1 || maxNum > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数设置错误！");
        }

        //   2. 队伍标题 <= 20
        String name = team.getName();
        if (StringUtils.isBlank(name) || name.length() > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍名称设置错误！");
        }

        //   3. 描述 <= 512
        String description = team.getDescription();
        if (StringUtils.isNotBlank(description) && description.length() > 512) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述过长！");
        }

        //   4. status 是否公开（int）不传默认为 0（公开）
        int status = Optional.ofNullable(team.getStatus()).orElse(0);
        TeamStatusEnum teamStatusValue = TeamStatusEnum.getTeamStatusValue(status);
        if (teamStatusValue == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态设置错误！");
        }

        //   5. 如果 status 是加密状态，一定要有密码，且密码 <= 32
        String password = team.getPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusValue)
                && (StringUtils.isBlank(password) || password.length() > 32)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码设置错误！");
        }
        //   6. 超时时间 > 当前时间
        Date expireDate = team.getExpireTime();
        if (new Date().after(expireDate)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "超时时间设置出现问题！");
        }
        //   7. 校验用户最多创建和加入 5（10）个队伍
        // todo 有bug，可能同时创建100个队伍
        int hasJoinNumber = this.getJoinNumber(loginUser);
        if (hasJoinNumber >= (userService.isAdmin(loginUser) ? 10 : 5)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍数量已达阈值");
        }

        //   8. 插入队伍信息到队伍表
        team.setId(null);
        team.setUserId(id);
        boolean flag = this.save(team);
        Long teamId = team.getId();
        if (!flag || teamId == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍创建失败！");
        }

        //   9. 插入用户 =》 队伍关系到关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(id);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        flag = userTeamService.save(userTeam);
        if (!flag){
            throw new RuntimeException("系统异常，插入关系数据失败！");
        }
        return teamId;
    }

    /**
     * 查询队伍
     * @return 团队信息
     */
    @Override
    public List<TeamUserVO> getTeamList(TeamQueryRequest teamQueryRequest, boolean isAdmin) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if (teamQueryRequest != null) {

            // 1. 根据队伍id查询
            Long id = teamQueryRequest.getId();
            if (id != null && id > 0) {
                queryWrapper.eq("id", id);
            }

             // 根据队伍id列表查询
            List<Long> teamIds = teamQueryRequest.getTeamIds();
            if (CollectionUtils.isNotEmpty(teamIds)) {
                queryWrapper.in("id", teamIds);
            }
             // 关键词查询（队伍名称和描述）
            String searchText = teamQueryRequest.getSearchText();
            if (StringUtils.isNotBlank(searchText)) {
                queryWrapper.and(qw -> qw
                        .like("name", searchText))
                        .or()
                        .like("description", searchText);
            }

            // 2. 根据队伍名称查询
            String name = teamQueryRequest.getName();
            if (StringUtils.isNotBlank(name)) {
                queryWrapper.like("name", name);
            }

            // 3. 根据队伍描述查询
            String description = teamQueryRequest.getDescription();
            if (StringUtils.isNotBlank(description)) {
                queryWrapper.like("description", description);
            }

            // 4. 根据队伍人数阈值查询
            Integer maxNum = teamQueryRequest.getMaxNum();
            if (maxNum != null && maxNum > 0) {
                queryWrapper.eq("maxNum", maxNum);
            }

            // 5. 根据创建者查询
            Integer userId = teamQueryRequest.getUserId();
            if (userId != null && userId > 0) {
                queryWrapper.eq("userId", userId);
            }

            // 6. 根据状态查询
            Integer status = teamQueryRequest.getStatus();
            TeamStatusEnum teamStatusValue = TeamStatusEnum.getTeamStatusValue(status);
            if (teamStatusValue == null) {
                teamStatusValue = TeamStatusEnum.PUBLIC;
            }
            if (!isAdmin && !TeamStatusEnum.PUBLIC.equals(teamStatusValue)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "没有权限！");
            }
            queryWrapper.eq("status", teamStatusValue.getValue());

        }

        // (如果需要)不展示过期的队伍
        queryWrapper.and(qw -> qw
                .gt("expireTime", new Date())
                .or()
                .isNull("expireTime")
        );

        // 根据条件查询队伍
        List<Team> teamList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(teamList))
        {
            return new ArrayList<> ();
        }

        List<TeamUserVO> teamUserVOList = new ArrayList<>();
        for (Team team : teamList) {
            Integer userId = team.getUserId();
            if (userId == null) {
                continue;
            }
            User user = userService.getById(userId);
            TeamUserVO teamUserVO = new TeamUserVO();
            BeanUtils.copyProperties(team, teamUserVO);

            // 用户信息脱敏
            if (user != null) {
                UserVO userVO = new UserVO();
                BeanUtils.copyProperties(user, userVO);
                teamUserVO.setCreateUser(userVO);
            }
            teamUserVOList.add(teamUserVO);
        }

        // 1. 自己写 SQL
        // 查询队伍和创建人的信息
        // select * from team t left join user u on t.userId = u.id
        // 查询队伍和已加入队伍成员的信息
        // select *
        // from team t
        //         left join user_team ut on t.id = ut.teamId
        //         left join user u on ut.userId = u.id;
        return teamUserVOList;
    }

    /**
     * 更新队伍信息
     * @param teamUpdateRequest 队伍更新请求体
     * @param loginUser 登录用户
     * @return 更新是否成功
     */
    @Override
    public boolean updateTeam(TeamUpdateRequest teamUpdateRequest, User loginUser) {
        if (teamUpdateRequest == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请求参数为空！");
        }
        Long id = teamUpdateRequest.getId();
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍id参数错误！");
        }
        Team oldTeam = this.getById(id);
        if (oldTeam == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "修改队伍不存在！");
        }
        if (!Objects.equals(oldTeam.getUserId(), loginUser.getId()) && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "没有权限！");
        }
        TeamStatusEnum status = TeamStatusEnum.getTeamStatusValue(teamUpdateRequest.getStatus());
        if (TeamStatusEnum.SECRET.equals(status)) {
            if (StringUtils.isBlank(teamUpdateRequest.getPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加密房间必须要设置密码！");
            }
        }
        Team team = new Team();
        BeanUtils.copyProperties(teamUpdateRequest, team);
        return this.updateById(team);
    }

    /**
     * 加入队伍
     * @param teamJoinRequest 加入队伍请求体
     * @param loginUser 登录用户
     * @return 加入是否成功
     */
    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        if (teamJoinRequest == null || loginUser == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请求参数为空！");
        }

        // 1. 队伍参数合法
        Long teamId = teamJoinRequest.getTeamId();

        // 2. 加入的队伍得存在
        Team team = getTeamById(teamId);

        // 3. 不得加入过期的队伍
        Date expireDate = team.getExpireTime();
        if (expireDate != null && expireDate.before(new Date())) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "队伍已过期！");
        }

        // 4. 加入的队伍状态需符合(密码需匹配)
        Integer status = team.getStatus();
        TeamStatusEnum teamStatusValue = TeamStatusEnum.getTeamStatusValue(status);
        if (TeamStatusEnum.PRIVATE.equals(teamStatusValue)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "禁止参加私有队伍！");
        }
        String password = team.getPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusValue)) {
            if (StringUtils.isBlank(password) || !team.getPassword().equals(password)){
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误！");
            }
        }

        // 5. 队伍数量限制以及不得重复加入
        int hasJoinNum = this.getJoinNumber(loginUser);
        if (hasJoinNum >= (userService.isAdmin(loginUser) ? 10 : 5)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入队伍数量已到最大值");
        }

        int userId = loginUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        queryWrapper.eq("teamId", teamId);
        long hasUserJoinTeam = userTeamService.count(queryWrapper);
        if (hasUserJoinTeam > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户已加入该队伍");
        }

        // 6. 队伍现有人数少于阈值
        long teamHasJoinNum = this.countTeamUserByTeamId(teamId);
        if (teamHasJoinNum >= team.getMaxNum()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "该队伍人数已达上限！");
        }

        // 7. 修改关系信息
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    /**
     * 退出队伍
     * @param teamQuitRequest 退出队伍请求体
     * @param loginUser 登录用户
     * @return 是否退出成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null || loginUser == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "请求参数为空！");
        }
        Long teamId = teamQuitRequest.getTeamId();
        Team team = getTeamById(teamId);
        int userId = loginUser.getId();
        UserTeam queryUserTeam = new UserTeam();
        queryUserTeam.setTeamId(teamId);
        queryUserTeam.setUserId(userId);
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>(queryUserTeam);
        long count = userTeamService.count(queryWrapper);
        if (count == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "未加入队伍");
        }
        long teamHasJoinNum = this.countTeamUserByTeamId(teamId);
        // 队伍只剩一人，解散
        if (teamHasJoinNum == 1) {
            // 删除队伍
            this.removeById(teamId);
        } else {
            // 队伍还剩至少两人
            // 是队长
            if (team.getUserId() == userId) {
                // 把队伍转移给最早加入的用户
                // 1. 查询已加入队伍的所有用户和加入时间
                QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
                userTeamQueryWrapper.eq("teamId", teamId);
                userTeamQueryWrapper.last("order by id asc limit 2");
                List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
                if (CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <= 1) {
                    throw new RuntimeException("系统异常");
                }
                UserTeam nextUserTeam = userTeamList.get(1);
                Integer nextTeamLeaderId = nextUserTeam.getUserId();
                // 更新当前队伍的队长
                Team updateTeam = new Team();
                updateTeam.setId(teamId);
                updateTeam.setUserId(nextTeamLeaderId);
                boolean result = this.updateById(updateTeam);
                if (!result) {
                    throw new RuntimeException("系统异常，更新队伍队长失败！");
                }
            }
        }
        // 移除关系
        return userTeamService.remove(queryWrapper);
    }

    /**
     * 解散队伍
     * @param id 队伍id
     * @param loginUser 登录用户
     * @return 是否成功解散
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTeam(long id, User loginUser) {
        // 校验队伍是否存在
        Team team = getTeamById(id);
        long teamId = team.getId();
        // 校验你是不是队伍的队长
        if (!Objects.equals(team.getUserId(), loginUser.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH, "无访问权限");
        }
        // 移除所有加入队伍的关联信息
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        boolean result = userTeamService.remove(userTeamQueryWrapper);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除队伍关联信息失败");
        }
        // 删除队伍
        return this.removeById(teamId);
    }

    /**
     * 根据 id 获取队伍信息
     *
     * @param teamId 队伍id
     * @return 队伍信息
     */
    private Team getTeamById(Long teamId) {
        if (teamId == null || teamId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍id参数错误");
        }
        Team team = this.getById(teamId);
        if (team == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "队伍不存在");
        }
        return team;
    }

    /**
     * 获取某队伍当前人数
     *
     * @param teamId 队伍id
     * @return 人数
     */
    private long countTeamUserByTeamId(long teamId) {
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        return userTeamService.count(userTeamQueryWrapper);
    }

    /**
     * 获取当前用户参加队伍的个数
     * @param loginUser 当前登录用户
     * @return 参加队伍的个数
     */
    @Override
    public int getJoinNumber(User loginUser) {
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        int id = loginUser.getId();

        // 查询队伍用户关系中的所有相关的队伍
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", id);
        List <UserTeam> TeamList = userTeamService.list(queryWrapper);
        List<Long> teamIdList = TeamList.stream().map(UserTeam::getTeamId).toList();
        log.info("teamIdList:{}", teamIdList);
        if (CollectionUtils.isEmpty(teamIdList)) {
            return 0;
        }

        // 查询其中有效的队伍个数
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        teamQueryWrapper.in("id", teamIdList)
                .gt("expireTime", LocalDateTime.now()); // 未过期
        return this.list(teamQueryWrapper).size();
    }
}




